#ifndef SERIALTHREAD_H
#define SERIALTHREAD_H

#include <QObject>
#include <QTimer>
#include <mutex>
#include <QSerialPort>

class QSerialPort;
class QSerialPortInfo;

enum
{
    CCITT_1 = 0,
    CCITT
};

class SerialThread : public QObject
{
    Q_OBJECT
public:
    explicit SerialThread(QObject *parent = 0);
    ~SerialThread();

    static SerialThread* Instance();

    bool IsOpen();
    bool IsUpdate();
    uint16_t reentrent_crc_16(uint8_t *data, int32_t len, uint8_t flag = CCITT);
    uint16_t inverse_crc_16(uint8_t *data, int32_t len, uint8_t flag = CCITT);
    bool inverse_crc_check(uint8_t *data, int32_t len, uint8_t flag = CCITT);

signals:
    void SignalSerialClose();
    void SignalUpdateProgress(int);
    void SignalUpdateTips(const QString &, quint8);
    void SignalSerialLog(const QString&);

public slots:
    void SlotSerialOpen(const QString&, unsigned int);
    void SlotSerialClose();

    void SlotUpdateFireware(const QByteArray&);
    void SlotUpdateStop();

    void SlotReset();

private slots:
    void SlotTimer();
    void SlotRead();
    void SlotPortError(QSerialPort::SerialPortError);

private:
    void write(const unsigned char* buf, unsigned int len);
    void ClosePort();

    void UpdateTips(const char*, uint8_t);

    QString byteArrayToHexStr(const QByteArray &);
    void writeLog(const char *, const unsigned char *, int );
    void writeLog(const char *, const char *);
    void writeLog(const QString&);

    unsigned char HexToChar(unsigned char);

private:
    QTimer* m_Timer;
    QThread* m_Thread;

    std::mutex m_Mutex;

private:
    QSerialPort* m_Port;
    QSerialPortInfo* m_PortInfo;

    quint8 fireSendBuf[64];
    quint8 fireRecvBuf[64];
    quint8 fireSendState = 0;
    quint8 fireRecvLen = 0;
    quint8 fireSendLen = 0;
    quint8 mUpdateState = 0;

    quint16 overTick = 0;
    quint8 overNum = 0;

    int mFirewareLen = 0;
    int sndfileSize = 0;

    bool m_IsOpen = false;
    bool m_IsUpdate = false;


    QByteArray mFireware;
};

#endif // SERIALTHREAD_H
